package com.swhysc.information.common.model;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author zmq
 * @Date 2023/8/31 15:06
 * @Description
 */
public class ResultBody<T> implements Serializable {
    private static final long serialVersionUID = -3948389268046368059L;

    private static boolean HIDE_STACK_FLAG;

    private Date timestamp = new Date();

    private Integer status;

    private String error;

    private String message;

    private String stackmessage;

    private String path;

    private T data;

    private Map<String, String> extraInfo = new HashMap<String, String>();

    private boolean success;


    public ResultBody() {
    }

    public Date getTimestamp() {
        return timestamp;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public String getPath() {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        return request.getRequestURI().toString();
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMessage() {
        if (message != null){
            return message;
        }
        return ResultStatus.getMessage(this.status);
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getStackmessage() {
        try {
            if (stackmessage != null) {
                return stackmessage;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return stackmessage;
        }
    }

    public void setStackmessage(String stackmessage) {
        this.stackmessage = stackmessage;
    }

    public void addExtraInfo(String key, String value) {
        extraInfo.put(key, value);
    }

    public Map<String, String> getExtraInfo() {
        return extraInfo;
    }

    public static ResultBody success() {
        ResultBody result = new ResultBody();
        result.setResultStatus(ResultStatus.SUCCESS);
        result.setSuccess(true);
        return result;
    }

    public static ResultBody success(Object data) {
        ResultBody result = new ResultBody();
        result.setResultStatus(ResultStatus.SUCCESS);
        result.setData(data);
        result.setSuccess(true);
        return result;
    }

    public static ResultBody failure(String message) {
        ResultBody result = new ResultBody();
        result.setResultStatus(ResultStatus.FAILURE);
        result.setMessage(message);
        result.setSuccess(false);
        return result;
    }

    public static ResultBody failure(ResultStatus resultCode) {
        ResultBody result = new ResultBody();
        result.setResultStatus(resultCode);
        result.setSuccess(false);
        return result;
    }

    public static ResultBody failure(ResultStatus resultCode, Throwable e) {
        ResultBody result = new ResultBody();
        result.setResultStatus(resultCode);
        result.setStackmessage(getStackTrace(e));
        result.setMessage(e.getMessage());
        result.setSuccess(false);
        return result;
    }

    public static ResultBody failure(ResultStatus resultStatus, Object data) {
        ResultBody result = new ResultBody();
        result.setResultStatus(resultStatus);
        result.setData(data);
        result.setSuccess(false);
        return result;
    }

    public static ResultBody failure(Integer status, String message, Object data, Throwable e) {
        ResultBody result = new ResultBody();
        result.setStatus(status);
        result.setMessage(message);
        result.setData(data);
        result.setStackmessage(getStackTrace(e));
        result.setSuccess(false);
        return result;
    }


    public void setResultStatus(ResultStatus resultStatus) {
        this.status = resultStatus.status();
        this.message = resultStatus.message();
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public static void setHideStackFlag(boolean flag) {
        HIDE_STACK_FLAG = flag;
    }

    public static String getStackTrace(Throwable t) {
        if (HIDE_STACK_FLAG) return "";
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            if (t == null) {
                return "";
            }
            t.printStackTrace(pw);
            return sw.toString();
        } finally {
            pw.close();
        }
    }
}
